package pers.cfeng.server.versionManage;

import pers.cfeng.server.txManage.TransactionManager;

/**
 * 判断版本跳跃
 */

public class Visibility {

    public static boolean isVersionSkip(TransactionManager tm, Transaction t, Entry e) {
        long tmax = e.getTmax();
        if(t.getLevel() == 0){
            return false;
        } else {
            return tm.isCommitted(tmax) && (tmax > t.getTid() || t.isInSnapshot(tmax));
        }
    }

    public static boolean isVisible(TransactionManager tm, Transaction t, Entry e) {
        if(t.getLevel() == 0) {
            return readCommitted(tm, t, e);
        } else {
            return repeatableRead(tm, t, e);
        }
    }

    /**
     * 读已提交级别下当前tid是否可见e
     */
    private static boolean readCommitted(TransactionManager tm, Transaction t, Entry e) {
        long tid = t.getTid();
        long tmin = e.getTmin();
        long tmax = e.getTmax();
        if(tmin == tid && tmax == 0)
            return true;

        if(tm.isCommitted(tmin)) {
            if(tmax == 0)
                return true;
            if(tmax != tid){
                if(!tm.isCommitted(tmax))
                    return true;
            }
        }
        return false;
    }

    //可重复读级别下可见性判断
    public static boolean repeatableRead(TransactionManager tm, Transaction t, Entry e) {
        long tid = t.getTid();
        long tmin = e.getTmin();
        long tmax = e.getTmax();
        if(tmin == tid && tmax == 0)
            return true;
        if(tm.isCommitted(tmin) && tmin < tid && !t.isInSnapshot(tmin)) {
            if(tmax == 0)
                return true;
            if(tmax != tid) {
                if(!tm.isCommitted(tmax) || tmax > tid || t.isInSnapshot(tmax))
                    return true;
            }
        }
        return false;
    }
}
